package org.idea.qiyu.framework.nacos.starter.client;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import org.idea.qiyu.framework.nacos.starter.bean.ModifyNacosPropertiesBean;
import org.idea.qiyu.framework.nacos.starter.properties.NacosProperties;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * @Author linhao
 * @Date created in 12:30 下午 2021/8/23
 */
@Component
public class NacosClientServiceImpl implements INacosClientService {

    @Resource
    public NacosProperties nacosProperties;

    @Override
    public String getProperty(String key, String dataId, String namespace, String groupId) throws NacosException {
        Map<String, String> resultMap = this.getAllProperty(dataId, namespace, groupId);
        if (resultMap != null) {
            String value = resultMap.get(key);
            return value;
        }
        return null;
    }

    @Override
    public Map<String, String> getAllProperty(String dataId, String namespace, String groupId) throws NacosException {
        Properties properties = new Properties();
        properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosProperties.getAddress());
        properties.put(PropertyKeyConst.NAMESPACE, namespace);
        ConfigService configService = NacosFactory.createConfigService(properties);
        String content = configService.getConfig(dataId, groupId, 3000);
        if (com.alibaba.nacos.client.utils.StringUtils.isNotBlank(content)) {
            String[] keyValueItem = content.split("\n");
            Map<String, String> resultMap = new HashMap<>(keyValueItem.length);
            for (int i = 0; i < keyValueItem.length; i++) {
                String nacosValue = keyValueItem[i];
                String[] keyValueStr = nacosValue.split("=");
                if (keyValueStr != null && keyValueStr.length == 2) {
                    String key = keyValueStr[0];
                    String value = keyValueStr[1];
                    resultMap.put(key, value);
                }
            }
            return resultMap;
        }
        return null;
    }

    @Override
    public boolean addProperties(ModifyNacosPropertiesBean modifyNacosPropertiesBean) throws NacosException {
        Map<String, String> oldConfigMap = this.getAllProperty(modifyNacosPropertiesBean.getDataId(), modifyNacosPropertiesBean.getNamespace(), modifyNacosPropertiesBean.getGroupId());
        Map<String, Object> newPropertiesMap = modifyNacosPropertiesBean.getPropertiesMap();
        for (String newKey : newPropertiesMap.keySet()) {
            oldConfigMap.put(newKey, String.valueOf(newPropertiesMap.get(newKey)));
        }
        if (oldConfigMap != null && oldConfigMap.size() > 0) {
            String newContent = this.buildNacosConfigStr(oldConfigMap);
            return this.publishConfig(
                    modifyNacosPropertiesBean.getDataId(),
                    modifyNacosPropertiesBean.getGroupId(),
                    modifyNacosPropertiesBean.getNamespace(),
                    newContent);
        }
        return false;
    }

    @Override
    public boolean publishConfig(String dataId, String groupId, String namespace, String content) throws NacosException {
        Properties properties = new Properties();
        properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosProperties.getAddress());
        properties.put(PropertyKeyConst.NAMESPACE, namespace);
        ConfigService configService = NacosFactory.createConfigService(properties);
        return configService.publishConfig(dataId, groupId, content);
    }

    @Override
    public boolean removeProperties(ModifyNacosPropertiesBean modifyNacosPropertiesBean) throws NacosException {
        Map<String, String> oldConfigMap = this.getAllProperty(modifyNacosPropertiesBean.getDataId(), modifyNacosPropertiesBean.getNamespace(), modifyNacosPropertiesBean.getGroupId());
        List<String> removeKeys = modifyNacosPropertiesBean.getRemoveKeys();
        for (String removeKey : removeKeys) {
            oldConfigMap.remove(removeKey);
        }
        String newContent = this.buildNacosConfigStr(oldConfigMap);
        this.publishConfig(
                modifyNacosPropertiesBean.getDataId(),
                modifyNacosPropertiesBean.getGroupId(),
                modifyNacosPropertiesBean.getNamespace(),
                newContent);
        return true;
    }

    @Override
    public boolean removeHoldConfig(String dataId, String groupId, String namespace) throws NacosException {
        Properties properties = new Properties();
        properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosProperties.getAddress());
        properties.put(PropertyKeyConst.NAMESPACE, namespace);
        ConfigService configService = NacosFactory.createConfigService(properties);
        return configService.removeConfig(dataId, groupId);
    }

    @Override
    public boolean addListener(String dataId, String groupId, String namespace, Listener listener) {
        Properties properties = new Properties();
        properties.setProperty(PropertyKeyConst.SERVER_ADDR, nacosProperties.getAddress());
        properties.put(PropertyKeyConst.NAMESPACE, namespace);
        try {
            ConfigService configService = NacosFactory.createConfigService(properties);
            configService.addListener(dataId, groupId, listener);
        } catch (NacosException e) {
            e.printStackTrace();
        }
        return false;
    }


    /**
     * 构建Nacos配置字符串
     *
     * @param propertiesMap
     * @return
     */
    private String buildNacosConfigStr(Map<String, String> propertiesMap) {
        StringBuffer stb = new StringBuffer();
        for (String key : propertiesMap.keySet()) {
            Object value = propertiesMap.get(key);
            stb.append(key + "=" + value + "\n");
        }
        return stb.toString();
    }

}
